
import { _decorator, Component, Node, v3, Widget, UITransform, Enum, UIOpacity, Tween, tween } from 'cc';
import EventManager from '../Managers/EventManager';
import { EventTypes } from '../Managers/EventTypes';
const { ccclass, property } = _decorator;
//入场方向
enum ExitDirection {
    None,
    Top,
    Bottom,
    Left,
    Right,
    Center_zoomOut, //放大
    Center_zoomIn,  //缩小
}
//缓动动画
enum EasingType {
    SineIn,
    SineOut,
    SineInOut,
    BackIn,
    BackOut,
    BackInOut,
}
//出场动画- 需要手动调用
@ccclass('UIExitAnimtions')
export class UIExitAnimtions extends Component {
    @property({ type: Enum(ExitDirection) })
    exitDirection: ExitDirection = ExitDirection.None;
    @property({ type: Enum(EasingType), visible() { return this.exitDirection != ExitDirection.None } })
    easingType: EasingType = EasingType.BackInOut;
    @property({ visible() { return this.exitDirection != ExitDirection.None && this.exitDirection != ExitDirection.Center_zoomOut } })
    moveDistRate = 1.5; //移动距离比例
    @property
    delayTime = 0;
    @property
    animTime = 0.5;
    @property
    isOpacityAnim = false;

    _initPos = v3();
    _initScale = v3();

    _cfg = ['sineIn', 'sineOut', 'sineInOut', 'backIn', 'backOut', 'backInOut'];
    _finishCb = null;
    _cbTween = { a: 0 };

    //记录子节点原本的状态
    _childrenRecs: { isActive: boolean, node: Node }[] = [];
    onLoad() {
        this.init();
    }

    init() {
        this._initPos.set(this.node.position);
        this._initScale.set(this.node.scale);
    }

    //外部更改
    seDelayTime(delayTime) {
        this.delayTime = delayTime;
    }

    onEnable(): void {
        Tween.stopAllByTarget(this._cbTween);
        Tween.stopAllByTarget(this._toPos);
        Tween.stopAllByTarget(this._toScale);
        Tween.stopAllByTarget(this._opacity);
    }

    onDisable() {
        Tween.stopAllByTarget(this._cbTween);
        Tween.stopAllByTarget(this._toPos);
        Tween.stopAllByTarget(this._toScale);
        Tween.stopAllByTarget(this._opacity);

        let wg = this.node.getComponent(Widget);
        if (wg) {
            wg.enabled = true;
        }
    }

    setFinishAnim(cb) {
        this._finishCb = cb;
    }
    // 外部调用
    _toPos = v3();
    _toScale = v3();
    // 动画结束之后是否自动隐藏
    isAutoHide = false;
    /**
     * 播放隐藏动画
     * @param isAutoHide 动画结束之后是否自动隐藏节点
     * @param cb 动画回调
     * @param [useTouchMask=false]  是否使用触摸遮罩
     */
    showHideAnim(isAutoHide, cb?, useTouchMask = false) {
        this.isAutoHide = isAutoHide;
        this._finishCb = cb;
        Tween.stopAllByTarget(this._cbTween);
        Tween.stopAllByTarget(this._toPos);
        Tween.stopAllByTarget(this._toScale);
        //方向动画
        if (this.exitDirection != ExitDirection.None) {
            let wg = this.node.getComponent(Widget);
            if (wg) {
                wg.enabled = false;
            }
            this._toScale.set(this.node.scale);
            this._toPos.set(this.node.position);

            let trans = this.node.getComponent(UITransform);

            switch (this.exitDirection) {
                case ExitDirection.Top:
                    this.topAnim(trans);
                    break;
                case ExitDirection.Bottom:
                    this.bottomAnim(trans);
                    break;
                case ExitDirection.Left:
                    this.leftAnim(trans);
                    break;
                case ExitDirection.Right:
                    this.rightAnim(trans);
                    break;
                case ExitDirection.Center_zoomIn:
                    this.centerZoomOutAnim(trans);
                    break;
                case ExitDirection.Center_zoomOut:
                    this.centerZoomInAnim(trans);
                    break;
                default:
                    break;
            }
        }
        //透明动画
        if (this.isOpacityAnim) {
            this.opacityAnim();
        }
        // 遮罩
        if (useTouchMask) {
            EventManager.emit(EventTypes.UIEvents.ShowTouchMask);
        }
        //计时回调-> 自动隐藏
        tween(this._cbTween).delay(this.delayTime + this.animTime).call(() => {
            this._finishCb && this._finishCb();
            this._finishCb = null;

            if (this.isAutoHide) {
                this.node.active = false;
            }
            if (useTouchMask) {
                EventManager.emit(EventTypes.UIEvents.HideTouchMask);
            }
        }).start();

    }
    //位移/缩放动画完成后回调-不包含透明动画
    private showAnimFinished() {
        //检测UIStayAnims
        let cmp = this.node.getComponent('UIStayAnimations');
        if (cmp && cmp.enabled && cmp['showAnim']) {
            cmp['showAnim']();
        }
    }

    //从上方出场 
    private topAnim(trans: UITransform) {
        let toY = this._toPos.y + trans.height * this.moveDistRate;
        this.node.setPosition(this._toPos);
        let easing: any = this._cfg[this.easingType];

        tween(this._toPos).delay(this.delayTime).to(this.animTime, { y: toY }, {
            easing: easing, onUpdate: () => {
                this.node.setPosition(this._toPos);
            }
        }).call(() => {
            this.showAnimFinished();
        }).start();


    }
    //下方
    private bottomAnim(trans: UITransform) {
        let toY = this._toPos.y - trans.height * this.moveDistRate;
        this.node.setPosition(this._toPos);
        let easing: any = this._cfg[this.easingType];

        tween(this._toPos).delay(this.delayTime).to(this.animTime, { y: toY }, {
            easing: easing, onUpdate: () => {
                this.node.setPosition(this._toPos);
            }
        }).call(() => {
            this.showAnimFinished();
        }).start();
    }
    //左方
    private leftAnim(trans: UITransform) {
        let toX = this._toPos.x - trans.width * this.moveDistRate;
        this.node.setPosition(this._toPos);
        let easing: any = this._cfg[this.easingType];

        tween(this._toPos).delay(this.delayTime).to(this.animTime, { x: toX }, {
            easing: easing, onUpdate: () => {
                this.node.setPosition(this._toPos);
            }
        }).call(() => {
            this.showAnimFinished();
        }).start();
    }
    //右方
    private rightAnim(trans: UITransform) {
        let toX = this._toPos.x + trans.width * this.moveDistRate;
        this.node.setPosition(this._toPos);
        let easing: any = this._cfg[this.easingType];

        tween(this._toPos).delay(this.delayTime).to(this.animTime, { x: toX }, {
            easing: easing, onUpdate: () => {
                this.node.setPosition(this._toPos);
            }
        }).call(() => {
            this.showAnimFinished();
        }).start();
    }
    //中心放大
    private centerZoomOutAnim(trans: UITransform) {
        this.node.setScale(this._toScale);
        let easing: any = this._cfg[this.easingType];

        tween(this._toScale).delay(this.delayTime).to(this.animTime, { x: this.moveDistRate, y: this.moveDistRate, z: this.moveDistRate }, {
            easing: easing, onUpdate: () => {
                this.node.setScale(this._toScale);
            }
        }).call(() => {
            this.showAnimFinished();
        }).start();
    }
    //中心缩小
    private centerZoomInAnim(trans: UITransform) {
        this.node.setScale(this._toScale);
        let easing: any = this._cfg[this.easingType];
        tween(this._toScale).delay(this.delayTime).to(this.animTime, { x: 0, y: 0, z: 0 }, {
            easing: easing, onUpdate: () => {
                this.node.setScale(this._toScale);
            }
        }).call(() => {
            this.showAnimFinished();
        }).start();
    }
    _uiOpacityCmp: UIOpacity = null;
    _opacity = { opacity: 255 };
    //透明动画
    private opacityAnim() {
        //有透明度组件时 则执行透明的变化动画
        if (!this._uiOpacityCmp) {
            this._uiOpacityCmp = this.node.getComponent(UIOpacity);
            if (!this._uiOpacityCmp) {
                this._uiOpacityCmp = this.node.addComponent(UIOpacity);
            }
        }
        Tween.stopAllByTarget(this._opacity);
        if (this._uiOpacityCmp) {
            this._opacity.opacity = 255;
            this._uiOpacityCmp.opacity = 255;
            tween(this._opacity).delay(this.delayTime).to(this.animTime, { opacity: 0 }, {
                onUpdate: () => {
                    this._uiOpacityCmp.opacity = this._opacity.opacity;
                }
            }).start();
        }
    }
}

